package com.daxue.common.http.core;

import com.daxue.common.http.utils.RateLimiterConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StringUtils;

import java.beans.ConstructorProperties;
import java.io.IOException;
import java.util.List;

/**
 * @author daxue0929
 * @date 2022/4/7
 */

public class RequestRateLimiterInterceptor implements ClientHttpRequestInterceptor {
    private static final Logger log = LoggerFactory.getLogger("com.yufu.idaas.extension.rest.base.core.RestClient");
    private static final String X_RATELIMITER_BUCKET = "x-ratelimiter-bucket";
    private final RateLimiterBuilder rateLimiterBuilder;
    private final String clientName;
    private final List<RateLimiterConfig> rateLimits;

    public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws
        IOException {
        HttpHeaders requestHeaders = request.getHeaders();
        if (requestHeaders.containsKey("x-ratelimiter-bucket")) {
            for(int i = 0; i < this.rateLimits.size(); ++i) {
                this.rateLimiterBuilder.build(StringUtils.arrayToDelimitedString(new String[]{this.clientName, requestHeaders.getFirst("x-ratelimiter-bucket"), Integer.toString(i)}, ":"), (RateLimiterConfig)this.rateLimits.get(i)).acquire();
            }
        }

        return execution.execute(request, body);
    }

    @ConstructorProperties({"rateLimiterBuilder", "clientName", "rateLimits"})
    public RequestRateLimiterInterceptor(final RateLimiterBuilder rateLimiterBuilder, final String clientName, final List<RateLimiterConfig> rateLimits) {
        this.rateLimiterBuilder = rateLimiterBuilder;
        this.clientName = clientName;
        this.rateLimits = rateLimits;
    }
}
